package edu.ntnu.superrss.service;

import edu.ntnu.superrss.models.SyndEntryImpl;
import edu.ntnu.superrss.models.User;
import edu.ntnu.superrss.utils.HibernateUtil;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.springframework.stereotype.Service;

/**
 *
 * @author Haakon Roekenes <hakondro at stud.ntnu.no>
 */
@Service
public class EntryServiceImpl implements EntryService {

    /**
     * Fetches a given entry from the database
     * <p>
     * This method fetches a given entry from the database, identified by a Long id
     *
     * @param user the User object to be modified, a fully qualified User object is expected
     * @param  id a Long with the primary key of the SyndEntryImpl in database
     * @throws  HibernateException
     */
    public SyndEntryImpl getEntry(Long id) throws HibernateException {

        Session session = HibernateUtil.getSessionFactory().openSession();
        Transaction tx = null;
        SyndEntryImpl entry = null;
        try {
            tx = session.beginTransaction();

            entry = (SyndEntryImpl) session.createQuery("From SyndEntryImpl where entryID = ?").setParameter(0, id).uniqueResult();

            session.flush();
            tx.commit();
        } catch (RuntimeException e) {
            tx.rollback();
            throw e; // TODO: LOG4J
        } finally {
            session.close();
        }
        return entry;
    }

    /**
     * Marks an entry as read and updates the database
     * <p>
     * This method marks a given entry as read, by the given user
     *
     * @param user the User object to be modified, a fully qualified User object is expected
     * @param  id a Long with the primary key of the SyndEntryImpl in database
     * @throws  HibernateException
     */
    public void markEntryRead(Long id, User user) throws HibernateException {
        SyndEntryImpl entry = getEntry(id);
        user.addEntryRead(entry);

        Session session = HibernateUtil.getSessionFactory().openSession();
        Transaction tx = null;
        try {
            tx = session.beginTransaction();

            session.merge(user);

            session.flush();
            tx.commit();
        } catch (RuntimeException e) {
            tx.rollback();
            throw e; // TODO: LOG4J
        } finally {
            session.close();
        }
    }

    /**
     * Marks an entry as thumbed up, indicating popularity of the given entry
     * <p>
     * A call to this method adds the entry to the entryThumbed list of a given user
     * This list is used to check if a user has thumbed up or not
     *
     * After adding the entry to the user list entriesRead, an attribute entriesThumbed in the entry is incremented
     *
     * @param user the User object to be modified, a fully qualified User object is expected
     * @param  id a Long with the primary key of the SyndEntryImpl in database
     * @throws  HibernateException
     */
    public void thumbUpEntry(Long id, User user) throws HibernateException {
        SyndEntryImpl entry = getEntry(id);
        user.addEntryThumbed(entry);

        Session session = HibernateUtil.getSessionFactory().openSession();
        Transaction tx = null;
        try {
            tx = session.beginTransaction();

            session.merge(user);
            session.merge(entry);

            session.flush();
            tx.commit();
        } catch (RuntimeException e) {
            tx.rollback();
            throw e; // TODO: LOG4J
        } finally {
            session.close();
        }
    }
}
